﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AmiEmuLib.AmigaMachine.AmigaMemory;
using AmiEmuLib.AmigaMachine.AmigaCPU;
using AmiEmuLib.AmigaMachine;
using System.Xml;
using System.Diagnostics;
using TomanuExtensions;

namespace AmiEmuLib.SaveState
{
    /// <summary>
    /// MC68000 state.
    /// </summary>
    public class CPU68000State : CPU680x0State

    {
        /// <summary>
        /// Prefetch.
        /// </summary>
        [DebuggerDisplay("{Hex.UIntToHex(IR)}")]
        public uint IR { get; private set; }

        /// <summary>
        /// Prefetch.
        /// </summary>
        [DebuggerDisplay("{Hex.UIntToHex(IRC)}")]
        public uint IRC { get; private set; }

        /// <summary>
        /// User stack pointer.
        /// </summary>
        [DebuggerDisplay("{Hex.UIntToHex(USP)}")]
        public uint USP { get; private set; }

        /// <summary>
        /// Supervisor stack pointer.
        /// </summary>
        [DebuggerDisplay("{Hex.UIntToHex(SSP)}")]
        public uint SSP { get; private set; }

        /// <summary>
        /// Status register.
        /// </summary>
        [DebuggerDisplay("{AmiEmuLib.AmigaMachine.AmigaCPU.SR68000.Info(SR)}, {AmiEmuLib.AmigaMachine.AmigaCPU.CCRRegistry.Info(SR)}")]
        public ushort SR { get; private set; }

        /// <summary>
        /// Constructor.
        /// </summary>
        internal CPU68000State()
        {
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="a_cpu"></param>
        /// <param name="a_prev"></param>
        internal CPU68000State(CPU68000 a_cpu, CPU68000State a_prev = null)
            : base(a_cpu, a_prev)
        {
            IR = a_cpu.IR;
            IRC = a_cpu.IRC;

            USP = a_cpu.USP;
            SSP = a_cpu.SSP;

            SR = a_cpu.SR;
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="a_prev"></param>
        internal CPU68000State(CPU680x0State a_prev) 
            : base(a_prev)
        {
        }

        internal override void Restore(CPU680x0 a_cpu)
        {
            CPU68000 cpu = (CPU68000)a_cpu;

            cpu.IR = IR;
            cpu.IRC = IRC;

            cpu.SSP = SSP;
            cpu.USP = USP;

            cpu.SR = SR;

            base.Restore(a_cpu);
        }

        /// <summary>
        /// Restore state from another state.
        /// </summary>
        /// <param name="Prev"></param>
        protected override void Restore(CPU680x0State a_cpu)
        {
            base.Restore(a_cpu);

            CPU68000State cpu = (CPU68000State)a_cpu;

            IR = cpu.IR;
            IRC = cpu.IRC;

            USP = cpu.USP;
            SSP = cpu.SSP;

            SR = cpu.SR;
        }

        public override bool Equals(object a_obj)
        {
            if (a_obj == null)
                return false;
            CPU68000State cpu = a_obj as CPU68000State;
            if (cpu == null)
                return false;

            return base.Equals(a_obj) && 
                   (IR == cpu.IR) &&
                   (IRC == cpu.IRC) &&
                   (USP == cpu.USP) &&
                   (SSP == cpu.SSP) &&
                   (SR == cpu.SR);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode() ^
                   IR.GetHashCode() ^
                   IRC.GetHashCode() ^
                   USP.GetHashCode() ^
                   SSP.GetHashCode() ^
                   SR.GetHashCode();
        }

        internal override void ReadXml(XmlReader a_reader)
        {
            if (a_reader.IsEmptyElement)
            {
                a_reader.ReadStartElement(GetType().Name);
                return;
            }

            a_reader.ReadStartElement(GetType().Name);

            base.ReadXml(a_reader);

            if (a_reader.IsStartElement("IR"))
                IR = a_reader.ReadElementContentAsHexUInt("IR");
            if (a_reader.IsStartElement("IRC"))
                IRC = a_reader.ReadElementContentAsHexUInt("IRC");

            if (a_reader.IsStartElement("SSP"))
                SSP = a_reader.ReadElementContentAsHexUInt("SSP");
            if (a_reader.IsStartElement("USP"))
                USP = a_reader.ReadElementContentAsHexUInt("USP");

            if (a_reader.IsStartElement("SR"))
                SR = a_reader.ReadElementContentAsHexUShort("SR");

            a_reader.ReadEndElement();
        }

        internal override void WriteXml(XmlWriter a_writer)
        {
            base.WriteXml(a_writer);

            CPU68000State prev = (CPU68000State)Prev;

            if (((prev != null) && (prev.IR != IR)) || (prev == null))
                a_writer.WriteHexElement("IR", IR);
            if (((prev != null) && (prev.IRC != IRC)) || (prev == null))
                a_writer.WriteHexElement("IRC", IRC);

            if (((prev != null) && (prev.SSP != SSP)) || (prev == null))
                a_writer.WriteHexElement("SSP", SSP);
            if (((prev != null) && (prev.USP != USP)) || (prev == null))
                a_writer.WriteHexElement("USP", USP);

            if (((prev != null) && (prev.SR != SR)) || (prev == null))
                a_writer.WriteHexElement("SR", SR);
        }
    }
}
